#include "vc1dec_definitions.h"
#include "vc1stream.h"
#include "vc1dec_api.h"
#include "vc1vlc.h"
#include "vc1tables.h"

#include "vc1decblk.h"

static HRESULT_VC1 VC1DecodeIMBHeader(sVC1Decoder* pDec,sVC1MB* pCur,I32_VC1 iMBx,I32_VC1 iMBy)
{
	sVC1MB *pLeft,*pTop,*pLeftTop;
	I32_VC1 iPredCBPY0,iPredCBPY1,iPredCBPY2,iPredCBPY3;
	I32_VC1 iTop2,iTop3,iLeft1,iLeft3,iLeftTop3;
	I32_VC1 CBP = 0;
	U32_VC1 CBPCY = 0;
	I32_VC1 i;
	sVC1Stream* pStream = &pDec->stream;

	CBP = VC1GetVLC(pStream,pDec->pICBPYTableSM,VC1CBPVLCPEEKBITS);

	pLeft = NULL;
	pTop = NULL;
	pLeftTop = NULL;

	if(iMBx != 0)
		pLeft = pCur - 1;

	if(iMBy != 0)
		pTop  = pCur - pDec->widthMBs;

	if(iMBy != 0 && iMBx != 0)
		pLeftTop = pCur - pDec->widthMBs - 1;


	if(pTop)
	{
		iTop2 = (pTop->CBP >> 3) & 1;
		iTop3 = (pTop->CBP >> 2) & 1;
	}
	else
	{
		iTop2 = 0;
		iTop3 = 0;
	}

	if(pLeft)
	{
		iLeft1 = (pLeft->CBP >> 4) & 1;
		iLeft3 = (pLeft->CBP >> 2) & 1;
	}
	else
	{
		iLeft1 = 0;
		iLeft3 = 0;
	}

	if(pLeftTop)
		iLeftTop3 = (pLeftTop->CBP >> 2) & 1;
	else
		iLeftTop3 = 0;

	iPredCBPY0 = (iLeftTop3 == iTop2) ? iLeft1 : iTop2;
	iPredCBPY0 ^= ((CBP >> 5) & 0x1);

	iPredCBPY1 = (iTop2 == iTop3) ? iPredCBPY0 : iTop3;
	iPredCBPY1 ^= ((CBP >> 4) & 0x1);

	iPredCBPY2 = (iLeft1 == iPredCBPY0) ? iLeft3 : iPredCBPY0;
	iPredCBPY2 = ((CBP >> 3) & 0x1);
	
	iPredCBPY3 = (iPredCBPY0 == iPredCBPY1) ? iPredCBPY2 :iPredCBPY1;
	iPredCBPY3 ^= ((CBP >> 2) & 0x1);

	pCur->CBP = (iPredCBPY0 << 5) | (iPredCBPY1 << 4) | (iPredCBPY2 << 3) | (iPredCBPY3 << 2) | (CBP & 0x3);

	pCur->mbtype = MB_Intra;
	pCur->skip = 0;
	pCur->MBCoded = INTRA;
	pCur->acpred = VC1GetBits(pStream,1);
	pCur->mquant = pDec->pquant;

	if(pDec->pquant >= 9 && pDec->overlap)
		pCur->default_dc = 0;
	else
	{
		I16_VC1 stepsize = VC1GetDCStepSize(pCur->mquant);
		pCur->default_dc = (1024 + (stepsize >> 1)) / stepsize;
	}

	for(i = 0; i < 6; i++)
		pCur->isIntra[i] = 1;

	return VC1_OK;

}

HRESULT_VC1 VC1DecodeIFrame(sVC1Decoder* pDec)
{
	HRESULT_VC1 rt = VC1_OK;
	I32_VC1 x,y;
	sVC1Stream* pStream = &pDec->stream;
	sVC1MB*     pMB     = pDec->pAllMBs;
	U8_VC1      *pY     = pDec->pCurPicture->Y;
	U8_VC1      *pU     = pDec->pCurPicture->U;
	U8_VC1      *pV     = pDec->pCurPicture->V;

	for(y = 0; y < pDec->heightMBs; y++)
	{
		for(x = 0; x < pDec->widthMBs; x++)
		{
			////decode MB header
			int blk = 0;
			U32_VC1 neighbor[4];
			U8_VC1* pMBY = pY + x * 16;
			U8_VC1* pMBU = pU + x * 8;
			U8_VC1* pMBV = pV + x * 8;
			sVC1MB* pCur = pMB + y * pDec->heightMBs + x;

			neighbor[0] = (x!=0) ? 1 : 0;
			neighbor[1] = (y!=0) ? 1 : 0; 
			neighbor[2] = (x!=0 && y!=0) ? 1 : 0;
			if((rt = VC1DecodeIMBHeader(pDec,pCur,x,y)) != VC1_OK)
				return VC1_UNKNOWERROR;

			if((rt = VC1DecBlocks(pDec,pCur,neighbor,pMBY,pMBU,pMBV,x)) != VC1_OK)
				return rt;
			
		}

		pY += 16 * pDec->pCurPicture->stride;
		pU += 8 * (pDec->pCurPicture->stride>>1);
		pV += 8 * (pDec->pCurPicture->stride>>1);
	}

	return rt;
}